
import unittest
from testPluginInterface import TestPluginInterface

## Internal functions ##

def value_matches(value, pattern):
    """ Value is same as pattern or match regexp-pattern """
    if hasattr(pattern, 'search') and isinstance(value, basestring):
        return bool(pattern.search(value))
    return bool(value == pattern)


def pitem_unmatches(item, **kwargs):
    """ Return list of attributes, that does not match patterns in kwargs """
    out = []
    # Special attributes, that may contain dictionary:
    for (attr, pattern) in kwargs.items():
        value = getattr(item, attr, '\0NOT-FOUND')

        if not hasattr(item, attr):
            out.append('item.%s does not exist' % (attr,))

        elif isinstance(pattern, dict) and isinstance(value, dict):
            # structured pattern:
            for (key, key_pattern) in pattern.items():
                if not value.has_key(key):
                    out.append('item.%s[%s] does not exist' % (attr, key))
                elif not value_matches(value[key], key_pattern):
                    out.append('item.%s[%s] does not match %r' \
                                % (attr, key, key_pattern))

        elif not value_matches(value, pattern):
            out.append('item.%s does not match %r' % (attr, pattern))
    out.sort()
    return out


class PluginTestCase(unittest.TestCase):
    """ Extended TestCase for testing plugins """
    PLUGIN_CLASS = None
    PLUGIN_ID = None

    def setUp(self):
        """ Setup test - initializes:
                self.iface  - testing interface instance
                self.plugin - plugin instance
        """
        if not self.PLUGIN_CLASS:
            raise Exception('%s.PLUGIN_CLASS must be defined' \
                                % self.__class__.__name__)
        self.iface = TestPluginInterface()
        self.plugin = self.PLUGIN_CLASS( self.iface )

    def tearDown(self):
        pass


    def assertPItemMatches(self, item, **kwargs):
        """ Test PItem attributes """
        failures = pitem_unmatches(item, **kwargs)
        if failures:
            errmsg = '\n'.join(failures) + "\nitem: " + repr(item)
            raise self.failureException, errmsg


    def assertPItemExists(self, **kwargs):
        """ assert that item exists and return this item """
        for item in self.iface.ITEMS:
            if not pitem_unmatches(item, **kwargs):
                return item
        raise self.failureException, 'PItem not found'



def main(*args, **kwargs):
    unittest.main(*args, **kwargs)

